/*
 * 文件名：OTAUpdate.cpp
 * 功能描述：OTA固件更新和远程升级
 */
#include "OTAUpdate.h"
#include "config.h"
#include <nvs.h>
#include <nvs_flash.h>
String firmwareName="";
String firmwareVersion="";
Preferences preferences;


// // 保存偏好设置
// void savePreferences() {
//     // 初始化NVS
//     esp_err_t err = nvs_flash_init();
//     if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
//         nvs_flash_erase(); // 清除NVS存储
//         err = nvs_flash_init(); // 重新初始化
//     }

//     if (err != ESP_OK) {
//         Serial.println("Failed to initialize NVS");
//         return;
//     }

//     nvs_handle my_handle;
//     err = nvs_open("settings", NVS_READWRITE, &my_handle); // 打开NVS存储空间
//     if (err != ESP_OK) {
//         // Serial.println("Failed to open NVS handle");
//         return;
//     }

//     // 使用 c_str() 方法将 String 转换为 const char* 类型
//     err = nvs_set_str(my_handle, "firmware_name", firmware_name_g.c_str());
//     if (err != ESP_OK) {
//         // Serial.println("Failed to write firmware_name");
//     }
//     err = nvs_set_str(my_handle, "firmware_v", firmware_version_g.c_str());
//     if (err != ESP_OK) {
//         // Serial.println("Failed to write firmware_v");
//     }
//     err = nvs_set_str(my_handle, "beepLevel", String(beepLevel_g).c_str());
//     if (err != ESP_OK) {
//         // Serial.println("Failed to write beepLevel");
//     }
//     err = nvs_set_str(my_handle, "speed", String(get_current_speed()).c_str());
//     if (err != ESP_OK) {
//         // Serial.println("Failed to write speed");
//     }
//     err = nvs_set_str(my_handle, "speaker", String(speaker_g).c_str());
//     if (err != ESP_OK) {
//         // Serial.println("Failed to write speaker");
//     }
//     err = nvs_set_str(my_handle, "level", String(level_difficulty_g).c_str());
//     if (err != ESP_OK) {
//         // Serial.println("Failed to write level");
//     }
//     err = nvs_set_str(my_handle, "mode", String(mode_g).c_str());
//     if (err != ESP_OK) {
//         // Serial.println("Failed to write mode_g");
//     }
//     // 写入数据
//     err = nvs_set_str(my_handle, "s_n_g", sn_g.c_str());
//     if (err != ESP_OK) {
//         // Serial.print("Failed to write sn, error code: ");
//     } 
//     // 提交写入的数据
//     err = nvs_commit(my_handle);
//     if (err != ESP_OK) {
//         // Serial.println("Failed to commit changes to NVS");
//     }

//     // 关闭NVS存储
//     nvs_close(my_handle);
// //
// //    logManager.writeFormattedLog("保存偏好设置：\n"
// //                                 "固件名称: %s\n"
// //                                 "固件版本: %s\n"
// //                                 "音量: %d\n"
// //                                 "速度: %d\n"
// //                                 "开关状态: %d\n"
// //                                 "难度: %d\n"
// //                                 "模式: %d",
// //                                 firmware_name_g.c_str(), firmware_version_g.c_str(), beepLevel_g, get_current_speed(), speaker_g, level_difficulty_g, mode_g);
// }

// // // 加载偏好设置
// // void loadPreferences() {
// //     esp_err_t err = nvs_flash_init();
// //     if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
// //         nvs_flash_erase(); // 清除NVS存储
// //         err = nvs_flash_init(); // 重新初始化
// //     }

// //     if (err != ESP_OK) {
// //         // Serial.println("Failed to initialize NVS");
// //         return;
// //     }

// //     nvs_handle my_handle;
// //     err = nvs_open("settings", NVS_READONLY, &my_handle); // 打开NVS存储空间
// //     if (err != ESP_OK) {
// //         // Serial.println("Failed to open NVS handle");
// //         return;
// //     }

// //     // 获取各个偏好设置
// //     size_t required_size;
// //     char* firmware_name = (char*) malloc(64);
// //     err = nvs_get_str(my_handle, "firmware_name", firmware_name, &required_size);
// //     if (err == ESP_OK) {
// //         firmware_name_g = String(firmware_name);
// //     } else {
// //         // Serial.println("Failed to read firmware_name");
// //     }

// //     char* firmware_v = (char*) malloc(64);
// //     err = nvs_get_str(my_handle, "firmware_v", firmware_v, &required_size);
// //     if (err == ESP_OK) {
// //         firmware_version_g = String(firmware_v);
// //     } else {
// //         // Serial.println("Failed to read firmware_v");
// //     }

// //     char* beep_level_str = (char*) malloc(64);
// //     err = nvs_get_str(my_handle, "beepLevel", beep_level_str, &required_size);
// //     if (err == ESP_OK) {
// //         beepLevel_g = String(beep_level_str).toInt();
// //     } else {
// //         // Serial.println("Failed to read beepLevel");
// //     }

// //     char* speed_str = (char*) malloc(64);
// //     err = nvs_get_str(my_handle, "speed", speed_str, &required_size);
// //     if (err == ESP_OK) {
// //         speed_set(String(speed_str).toInt());
// //     } else {
// //         // Serial.println("Failed to read speed");
// //     }

// //     char* speaker_str = (char*) malloc(64);
// //     err = nvs_get_str(my_handle, "speaker", speaker_str, &required_size);
// //     if (err == ESP_OK) {
// //         speaker_g = String(speaker_str).toInt();
// //     } else {
// //         // Serial.println("Failed to read speaker");
// //     }

// //     char* level_str = (char*) malloc(64);
// //     err = nvs_get_str(my_handle, "level", level_str, &required_size);
// //     if (err == ESP_OK) {
// //         level_difficulty_g = String(level_str).toInt();
// //     } else {
// //         // Serial.println("Failed to read level");
// //     }

// //     char* mode_str = (char*) malloc(64);
// //     err = nvs_get_str(my_handle, "mode", mode_str, &required_size);
// //     if (err == ESP_OK) {
// //         mode_g = String(mode_str).toInt();
// //     } else {
// //         // Serial.println("Failed to read mode_g");
// //     }
// //     // 获取需要的大小
// // err = nvs_get_str(my_handle, "s_n_g", NULL, &required_size);
// // char* sn_str;
// // if (err == ESP_OK) {
// //     sn_str = (char*) malloc(required_size);  // 根据需要的大小分配内存
// //     err = nvs_get_str(my_handle, "s_n_g", sn_str, &required_size);
// //     if (err == ESP_OK) {
// //         sn_g = String(sn_str);
// //         // Serial.println("Successfully read sn_g: " + sn_g);
// //     } else {
// //         // Serial.print("Failed to read sn_g, error code: ");
// //         Serial.println(err);
// //     }
// // }
// // free(sn_str);  // 释放分配的内存

// //     // 关闭NVS存储
// //     nvs_close(my_handle);

// // }


// // 读取 NVS 字符串并返回读取的值
// String readStringFromNVS(nvs_handle my_handle, const char* key) {
//     size_t required_size;
//     esp_err_t err = nvs_get_str(my_handle, key, NULL, &required_size);
//     if (err != ESP_OK) {
//         // Serial.println("Failed to read " + String(key));
//         return "";  // 如果读取失败，返回空字符串
//     }

//     char* str = (char*) malloc(required_size);
//     if (str == NULL) {
//         // Serial.println("Failed to allocate memory for " + String(key));
//         return "";  // 如果分配内存失败，返回空字符串
//     }

//     err = nvs_get_str(my_handle, key, str, &required_size);
//     String result = (err == ESP_OK) ? String(str) : "";  // 读取成功则返回字符串，否则返回空字符串
//     free(str);  // 释放内存
//     return result;
// }

// // 加载偏好设置
// void loadPreferences() {
//     esp_err_t err = nvs_flash_init();
//     if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
//         nvs_flash_erase(); // 清除NVS存储
//         err = nvs_flash_init(); // 重新初始化
//     }

//     if (err != ESP_OK) {
//         // Serial.println("Failed to initialize NVS");
//         return;
//     }

//     nvs_handle my_handle;
//     err = nvs_open("settings", NVS_READONLY, &my_handle); // 打开NVS存储空间
//     if (err != ESP_OK) {
//         // Serial.println("Failed to open NVS handle");
//         return;
//     }

//     // 获取各个偏好设置
//     firmware_name_g = readStringFromNVS(my_handle, "firmware_name");
//     firmware_version_g = readStringFromNVS(my_handle, "firmware_v");
//     beepLevel_g = readStringFromNVS(my_handle, "beepLevel").toInt();
//     speed_set(readStringFromNVS(my_handle, "speed").toInt());
//     speaker_g = readStringFromNVS(my_handle, "speaker").toInt();
//     level_difficulty_g = readStringFromNVS(my_handle, "level").toInt();
//     mode_g = readStringFromNVS(my_handle, "mode").toInt();
//     sn_g = readStringFromNVS(my_handle, "s_n_g");

//     // 关闭NVS存储
//     nvs_close(my_handle);
// }


// 从服务器读取固件信息的函数
bool Read_firmware(const char* ip,const int16_t port){
    WiFiClient client; // 创建一个WiFi客户端实例

    // 尝试连接到服务器
    if (!client.connect(ip, port)) {
        if (print_key)
        {
            Serial.println("连接服务器失败"); // 如果连接失败，打印错误信息
        }
        return false;
    }

    // 发送HTTP GET请求以获取固件文件
    client.print(String("GET /firmware.bin HTTP/1.1\r\n") +
                 "Host: " + ip + "\r\n" +
                 "Connection: close\r\n\r\n");

    // 读取响应头
    while (client.connected()) {
        String line = client.readStringUntil('\n'); // 读取每一行直到换行符

        if (line == "\r") {
            break;  // 如果读取到空行，表示HTTP响应头结束
        }

        line.trim();  // 去除字符串两端的空白字符

        // 查找并解析特定响应头（例如"Firmware-Name"）
        if (line.startsWith("Firmware-Name")) {
            firmwareName = line.substring(line.indexOf(':') + 2); // 获取冒号后面的值
            if (print_key)
            {
                Serial.println("最新固件名字: " + firmwareName); // 打印固件名称
            }
        }
        // 查找并解析特定响应头（例如"Firmware-Version"）
        if (line.startsWith("Firmware-Version")) {
            firmwareVersion = line.substring(line.indexOf(':') + 2); // 获取冒号后面的值
            if (print_key)
            {
                Serial.println("最新固件版本: " + firmwareVersion); // 打印固件版本
            }
        }

    }


    if (firmwareName!=firmware_name_g || firmwareVersion!=firmware_version_g){
        if (print_key)
        {
            Serial.println("有新版本固件！"); // 打印固件版本
        }
        return true;
    }else{
        if (print_key)
        {
            Serial.println("当前是新固件！");
        }
        return false;
    }
}


void updateOTA(const char* serverUrl) {
    WiFiClient client; // 创建一个WiFi客户端实例
    HTTPClient http; // 创建一个HTTP客户端实例

    // 配置HTTP客户端
    http.begin(client, serverUrl); // 开始HTTP连接，并指定服务器URL

    int httpCode = http.GET(); // 发送GET请求并获取响应码

    if (httpCode == HTTP_CODE_OK) { // 如果响应码为200，表示请求成功
        // 获取文件大小
        size_t fileSize = http.getSize(); // 获取固件文件的大小
        if (print_key)
        {
            Serial.println("File size: " + String(fileSize) + " bytes"); // 打印文件大小
        }

        // 如果文件大小未知，则退出
        if (fileSize == -1) {
            if (print_key)
            {
                Serial.println("Failed to get file size"); // 打印错误信息
            }
            return; // 结束函数执行
        }

        // 开始更新，指定固件大小
        if (!Update.begin(fileSize)) {
            if (print_key)
            {
                Serial.println("Update begin error: " + String(Update.errorString())); // 打印更新开始的错误信息
            }
            return; // 结束函数执行
        }

        // 使用HTTP客户端读取数据并写入固件
        WiFiClient& stream = http.getStream(); // 获取HTTP数据流
        uint8_t buff[128] = { 0 }; // 创建一个缓冲区用于存储读取的数据
        size_t written = 0; // 初始化已写入的字节数
        if (print_key)
        {
            Serial.println("下载代码中···"); // 打印更新开始信息
        }

        // 手动读取流并写入固件
        while (http.connected() && (written < fileSize || fileSize == -1)) {
            int len = stream.read(buff, sizeof(buff)); // 从流中读取数据到缓冲区
            if (len > 0) {
                written += Update.write(buff, len); // 将缓冲区中的数据写入固件

                // 计算并显示进度
                float progress = (written / (float)fileSize) * 100;
                if (print_key)
                {
                    Serial.printf("Download Progress: %.1f%%\n", progress);
                }


            }
        }

        // 检查是否所有数据都已写入
        if (written == fileSize) {
            if (print_key)
            {
                Serial.println("烧录完成！"); // 打印更新成功信息
                Serial.println("Update Success: " + String(written) + " bytes"); // 打印更新成功信息
            }

        } else {
            if (print_key)
            {
                Serial.println("Update Failed"); // 打印更新失败信息
            }
        }

        // 结束更新
        if (Update.end()) {
            if (print_key)
            {
                Serial.println("Update completed"); // 打印更新完成信息
            }
            if (Update.isFinished()) {
                // 打开preferences命名空间
                preferences.begin("firmware", false);
                preferences.putString("firmware_name", firmwareName);
                preferences.putString("firmware_version", firmwareVersion);
                firmware_name_g=firmwareName;
                firmware_version_g=firmwareVersion;
                // 关闭preferences
                preferences.end();

                if (print_key)
                {
                    Serial.println("Rebooting..."); // 打印重启信息
                }
                delay(1000);
                ESP.restart(); // 重启设备以应用新固件
            } else {
                if (print_key)
                {
                    Serial.println("Update not finished! Something went wrong."); // 打印更新未完成信息
                }
            }
        } else {
            if (print_key)
            {
                Serial.println("Update failed."); // 打印更新失败信息
            }
        }
    } else {
        if (print_key)
        {
            Serial.println("HTTP error code " + String(httpCode)); // 打印HTTP错误码
        }
    }

    // 关闭HTTP连接
    http.end(); // 结束HTTP连接
}
